package unitTest;

import com.mic.yzzn.plc.common.ins.datastructure.PLCContactorNumber;
import com.mic.yzzn.plc.common.ins.datastructure.PLCDataRegisterNumber;
import com.mic.yzzn.plc.common.instructions.basic.PLCRequestInstruction;
import com.mic.yzzn.plc.common.instructions.request.*;
import com.mic.yzzn.plc.common.toolUtils.PLCContactorCode;
import com.mic.yzzn.plc.common.toolUtils.PLCDataCode;
import com.mic.yzzn.plc.core.control.datastructure.PLCStationConfig;
import com.mic.yzzn.plc.core.control.datastructure.TCPStationConfig;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;

/**
 * 负责读取配置文件的类
 */
public class PLC_TestXMLParser implements Serializable
{

	/** 最大寄存器读取范围 */
	public int maxDataRegisterRange = 20;
	/** 最大触点读取范围 */
	public int maxContactorRange = 8;
	/** 测试采集器工作配置信息 */
	ArrayList<PLCStationConfig> stationConfigs = new ArrayList<PLCStationConfig>();
	/** 采集器对应的线程数量 */
	HashMap<String, Integer> stationRealTimeReadThreadNumber = new HashMap<>();

	HashMap<String, Integer> stationRealTimeWriteThreadNumber = new HashMap<>();

	HashMap<String, Integer> stationBufferdReadThreadNumber = new HashMap<>();

	HashMap<String, ArrayList> buffredReadDPointsMap = new HashMap<>();

	HashMap<String, ArrayList> buffredReadRPointsMap = new HashMap<>();

	HashMap<String, ArrayList> writeInstructionsMap = new HashMap<>();

	public ArrayList<PLCStationConfig> getstationConfigs()
	{
		return stationConfigs;
	}

	public HashMap<String, Integer> getStationRealTimeReadThreadNumber()
	{
		return stationRealTimeReadThreadNumber;
	}

	public HashMap<String, Integer> getStationRealTimeWriteThreadNumber()
	{
		return stationRealTimeWriteThreadNumber;
	}

	public HashMap<String, Integer> getStationBufferdReadThreadNumber()
	{
		return stationBufferdReadThreadNumber;
	}

	public HashMap<String, ArrayList> getBuffredReadDPointsMap()
	{
		return buffredReadDPointsMap;
	}

	public HashMap<String, ArrayList> getBuffredReadRPointsMap()
	{
		return buffredReadRPointsMap;
	}

	public HashMap<String, ArrayList> getWriteInstructionsMap()
	{
		return writeInstructionsMap;
	}

	/**
	 * 从XML中解析指令
	 * @param uri XML文件的URI
	 * @throws Exception 异常
	 */
	public void parseXMLFileFromURI(String uri) throws Exception
	{
		// 设置状态
		DocumentBuilderFactory dBuilderFactory = DocumentBuilderFactory.newInstance();

		try
		{
			// 读入XML
			DocumentBuilder dBuilder = dBuilderFactory.newDocumentBuilder();
			Document doc = dBuilder.parse(uri);

			// 读取Station
			parseStation(doc);

		}
		catch (Exception e)
		{
			e.printStackTrace();
		}

	}

	/**
	 * 移除字符串中所有的空格
	 * @param originalString
	 * @return
	 */
	private String removeBlank(String originalString)
	{
		return StringUtils.deleteWhitespace(originalString);
	}

	/**
	 * 返回station节点的字符串(已经删除空格)
	 * @param stationElement
	 * @return
	 */
	private String stationString(Element stationElement)
	{
		StringBuffer stationString = new StringBuffer();

		NodeList childNodes = stationElement.getChildNodes();

		// 遍历Station子节点
		for (int i = 0; i < childNodes.getLength(); ++i)
		{
			Node stationChild = childNodes.item(i);

			if (stationChild.getNodeName().equals("DataSection"))
			{
				NodeList dataSectionChildNodes = stationChild.getChildNodes();

				stationString.append(removeBlank(((Element)stationChild).getAttribute("class")));

				for (int j = 0; j < dataSectionChildNodes.getLength(); ++j)
				{
					Node dataSectionChild = dataSectionChildNodes.item(j);
					stationString.append(removeBlank(dataSectionChild.getTextContent()));
				}
			}
			else if (stationChild.getNodeName().equals("ContactPoint"))
			{
				stationString.append(removeBlank(((Element)stationChild).getAttribute("class")));
				stationString.append(removeBlank(stationChild.getTextContent()));
			}
			else
			{
				stationString.append(removeBlank(stationChild.getTextContent()));
			}
		}

		return stationString.toString();
	}

	/**
	 * 解析station节点
	 * @param doc
	 */
	private void parseStation(Document doc)
	{
		NodeList stations = doc.getElementsByTagName("Station");

		// 遍历所有Station节点
		for (int c = 0; c < stations.getLength(); ++c)
		{
			Element stationNode = (Element)stations.item(c);

			// 获取hash值
			String hash = DigestUtils.md5Hex(stationString(stationNode));
			NodeList hostNode = stationNode.getElementsByTagName("Host");
			NodeList portNode = stationNode.getElementsByTagName("Port");
			NodeList locNode = stationNode.getElementsByTagName("LocationNumber");

			// 初始化stationConfig
			PLCStationConfig stationConfig = new TCPStationConfig(hostNode.item(0).getTextContent(), Integer.parseInt(portNode.item(0).getTextContent()), locNode.item(0).getTextContent());
			stationConfig.XMLFieldHashCode = hash;
			// 装该Station中所有读指令的数组
			ArrayList<PLCRequestInstruction> instructions = new ArrayList<PLCRequestInstruction>();
			// 装该Station中所有R点的数组
			ArrayList<PLCContactorNumber> rPoints = new ArrayList<>();
			// 装该Station中所有D点的数组
			ArrayList<PLCDataRegisterNumber> dPoints = new ArrayList<>();
			// 装该Station中所有写指令的数组
			ArrayList<PLCRequestInstruction> writeIns = new ArrayList<>();

			// 站号字符串
			String locationNumber = locNode.item(0).getTextContent();
			// 刷新时间
			long flashTime = 0;

			// 获取stationNode的子节点
			NodeList childNodes = stationNode.getChildNodes();
			// 遍历Station所有子节点
			for (int i = 0; i < childNodes.getLength(); ++i)
			{
				Node stationChild = childNodes.item(i);

				String value = stationChild.getTextContent();

				if (stationChild.getNodeName().equals("CycleFlashTime"))
				{
					// 刷新时间
					flashTime = Integer.parseInt(value);
				}

				if (stationChild.getNodeName().equals("RealTimeReadMissionThreadCount"))
				{
					// 线程数量
					stationRealTimeReadThreadNumber.put(stationConfig.XMLFieldHashCode, Integer.parseInt(value));
				}
				if (stationChild.getNodeName().equals("RealTimeWriteMissionThreadCount"))
				{
					stationRealTimeWriteThreadNumber.put(stationConfig.XMLFieldHashCode, Integer.parseInt(value));
				}
				if (stationChild.getNodeName().equals("BufferedMissionThreadCount"))
				{
					stationBufferdReadThreadNumber.put(stationConfig.XMLFieldHashCode, Integer.parseInt(value));
				}

				// 离散点配置
				if (stationChild.getNodeName().equals("ContactPoint"))
				{
					String classType = ((Element)stationChild).getAttribute("class");
					String address = ((Element)stationChild).getTextContent();

					if (classType.equals(PLCDataCode.PLC_DATA_REGISTER_CODE))
					{
						PLCDataRegisterReadInstruction dri = new PLCDataRegisterReadInstruction();
						try
						{
							dri.setLocationNumber(locationNumber);
							dri.setDataRegisterNumber(new PLCDataRegisterNumber(address, address));
							dri.setDataCode(classType);
							dri.setBBC();
						}
						catch (IllegalAccessException e)
						{
							e.printStackTrace();
						}

						instructions.add(dri);
					}
					else if (classType.equals(PLCContactorCode.PLC_INNER_RELAY_CODE))
					{
						PLCSingleContactorReadInstruction sci = new PLCSingleContactorReadInstruction();
						try
						{
							sci.setLocationNumber(locationNumber);
							sci.setContactorNumber(new PLCContactorNumber(address));
							sci.setContactorCode(classType);
							sci.setBBC();
						}
						catch (IllegalAccessException e)
						{
							e.printStackTrace();
						}

						instructions.add(sci);
					}
				}

				// 缓存离散点配置
				if (stationChild.getNodeName().equals("BufferedContactPoint"))
				{
					String pointClassType = ((Element)stationChild).getAttribute("class");
					String address = ((Element)stationChild).getTextContent();

					if (pointClassType.equals(PLCDataCode.PLC_DATA_REGISTER_CODE))
					{
						PLCDataRegisterNumber dNumber = new PLCDataRegisterNumber(address, address);
						dPoints.add(dNumber);
					}
					else if (pointClassType.equals(PLCContactorCode.PLC_INNER_RELAY_CODE))
					{
						PLCContactorNumber rNumber = new PLCContactorNumber(
								address.substring(0, 3),
								address.charAt(3)
						);
						rPoints.add(rNumber);
					}
				}

				// 如果是dataSection节点则解析指令
				if (stationChild.getNodeName().equals("DataSection"))
				{
					NodeList dataSectionChildNodes = stationChild.getChildNodes();

					String classType = ((Element)stationChild).getAttribute("class");
					String beginAddress = "";
					String endAddress = "";

					for (int j = 0; j < dataSectionChildNodes.getLength(); ++j)
					{
						Node dataSectionChild = dataSectionChildNodes.item(j);
						// 取出起始地址
						if (dataSectionChild.getNodeName().equals("BeginAddress"))
						{
							beginAddress = dataSectionChild.getTextContent();
						}
						// 取出终止地址
						if (dataSectionChild.getNodeName().equals("EndAddress"))
						{
							endAddress = dataSectionChild.getTextContent();
						}
					}

					// 解析指令并且添加到数组中
					if (classType.equals(PLCDataCode.PLC_DATA_REGISTER_CODE))
					{
						instructions.addAll(parseDataRegisterReadInstruction(locationNumber, beginAddress, endAddress));
					}
					if (classType.equals(PLCContactorCode.PLC_INNER_RELAY_CODE))
					{
						instructions.addAll(parseContactorReadInstruction(locationNumber, beginAddress, endAddress));
					}

				}

				// 如果是缓存连续点读取配置
				if (stationChild.getNodeName().equals("BufferedDataSection"))
				{
					NodeList dataSectionChildNodes = stationChild.getChildNodes();

					String classType = ((Element)stationChild).getAttribute("class");
					String beginAddress = "";
					String endAddress = "";

					for (int j = 0; j < dataSectionChildNodes.getLength(); ++j)
					{
						Node dataSectionChild = dataSectionChildNodes.item(j);
						// 取出起始地址
						if (dataSectionChild.getNodeName().equals("BeginAddress"))
						{
							beginAddress = dataSectionChild.getTextContent();
						}
						// 取出终止地址
						if (dataSectionChild.getNodeName().equals("EndAddress"))
						{
							endAddress = dataSectionChild.getTextContent();
						}
					}

					// 解析编号添加到数组中
					if (classType.equals(PLCDataCode.PLC_DATA_REGISTER_CODE))
					{
						dPoints.addAll(parseDataRegisterNumbers(beginAddress, endAddress));
					}
					if (classType.equals(PLCContactorCode.PLC_INNER_RELAY_CODE))
					{
						rPoints.addAll(parseContactorNumbers(beginAddress, endAddress));
					}
				}

				// 写入离散点
				if (stationChild.getNodeName().equals("WriteContactPoint"))
				{
					NodeList writePointChildNodes = stationChild.getChildNodes();
					String writeType = ((Element)stationChild).getAttribute("class");
					String data = "";
					String pointStr = "";

					for (int j = 0; j < writePointChildNodes.getLength(); ++j)
					{
						Node writePointNode = writePointChildNodes.item(j);

						if (writePointNode.getNodeName().equals("Point"))
						{
							pointStr = writePointNode.getTextContent();
						}
						if (writePointNode.getNodeName().equals("Data"))
						{
							data = writePointNode.getTextContent();
						}
					}

					if (writeType.equals(PLCContactorCode.PLC_INNER_RELAY_CODE))
					{
						PLCContactorNumber rPoint = new PLCContactorNumber(pointStr.substring(0, 3), pointStr.charAt(3));
						PLCSingleContactorWriteInstruction wins = new PLCSingleContactorWriteInstruction();
						wins.setLocationNumber_high(locationNumber.substring(0, 1));
						wins.setLocationNumber_low(locationNumber.substring(1, 2));
						wins.setContactorCode(writeType);
						wins.setContactorNumber(rPoint);
						if (data.equals("1"))
						{
							wins.setContactorOn();
						}
						else
						{
							wins.setContactorOff();
						}
						wins.setBBC();
						writeIns.add(wins);
//						System.out.println(wins);
					}
					if (writeType.equals(PLCDataCode.PLC_DATA_REGISTER_CODE))
					{
						PLCDataRegisterNumber dPoint = new PLCDataRegisterNumber(pointStr, pointStr);
						PLCDataRegisterWriteInstruction wins = new PLCDataRegisterWriteInstruction();
						wins.setLocationNumber_high(locationNumber.substring(0, 1));
						wins.setLocationNumber_low(locationNumber.substring(1, 2));
						wins.setDataCode(writeType);
						wins.setDataRegisterNumber(dPoint);
						ArrayList<String> datas = new ArrayList<>();
						datas.add(data);
						wins.setWriteData(datas);
						wins.setBBC();
						writeIns.add(wins);
//						System.out.println(wins);
					}

				}

				// 写入连续点
				if (stationChild.getNodeName().equals("WriteDataSection"))
				{
					NodeList writeDataSectionChildNodes = stationChild.getChildNodes();

					String classType = ((Element)stationChild).getAttribute("class");
					String beginAddress = "";
					String endAddress = "";
					String data = "";

					for (int j = 0; j < writeDataSectionChildNodes.getLength(); ++j)
					{
						Node dataSectionChild = writeDataSectionChildNodes.item(j);
						// 取出起始地址
						if (dataSectionChild.getNodeName().equals("BeginAddress"))
						{
							beginAddress = dataSectionChild.getTextContent();
						}
						// 取出终止地址
						if (dataSectionChild.getNodeName().equals("EndAddress"))
						{
							endAddress = dataSectionChild.getTextContent();
						}
						// 取出数据
						if (dataSectionChild.getNodeName().equals("Data"))
						{
							data = dataSectionChild.getTextContent();
						}
					}

					// 解析编号添加到数组中
					if (classType.equals(PLCDataCode.PLC_DATA_REGISTER_CODE))
					{
						writeIns.addAll(parseDataRegisterWriteInstruction(locationNumber, beginAddress, endAddress, data));
					}
					if (classType.equals(PLCContactorCode.PLC_INNER_RELAY_CODE))
					{
						writeIns.addAll(parseContactorWriteInstruction(locationNumber, beginAddress, endAddress, data));
					}
				}
			}

			// station创建完毕,设置为新创建的station,放进Map中
			buffredReadDPointsMap.put(stationConfig.XMLFieldHashCode, dPoints);
			buffredReadRPointsMap.put(stationConfig.XMLFieldHashCode, rPoints);
			writeInstructionsMap.put(stationConfig.XMLFieldHashCode, writeIns);
			stationConfig.setInstructionList(instructions);
			stationConfig.updateTime = new Date();
			stationConfig.overdue = false;
			stationConfig.setLocationNumber(locationNumber);
			stationConfig.setFlashTime(flashTime);
			stationConfigs.add(stationConfig);
		}
	}

	/**
	 * 解析数据寄存器编号方法
	 * @param beginAddress 起始地址
	 * @param endAddress 结束地址
     * @return 读取后的数据寄存器编号数组
     */
	private ArrayList<PLCDataRegisterNumber> parseDataRegisterNumbers(String beginAddress, String endAddress)
	{
		PLCDataRegisterNumber registerNumber = new PLCDataRegisterNumber(beginAddress, endAddress);
		ArrayList<PLCDataRegisterNumber> returnArray = new ArrayList<PLCDataRegisterNumber>();
		returnArray.add(registerNumber);

		return returnArray;
	}

	/**
	 * 解析触点编号方法
	 * @param beginAddress 起始地址
	 * @param endAddress 结束地址
     * @return 读取后的触点编号数组
     */
	private ArrayList<PLCContactorNumber> parseContactorNumbers(String beginAddress, String endAddress)
	{
		ArrayList<PLCContactorNumber> returnArray = new ArrayList<PLCContactorNumber>();

		// 初始化触点编号
		PLCContactorNumber beginNumber = new PLCContactorNumber(beginAddress.substring(0, beginAddress.length() - 1),
				beginAddress.charAt(beginAddress.length() - 1));
		PLCContactorNumber endNumber = new PLCContactorNumber(endAddress.substring(0, endAddress.length() - 1),
				endAddress.charAt(endAddress.length() - 1));
		// 获取地址两个编号的差值
		int range = PLCContactorNumber.rangeOf(beginNumber, endNumber);

		for (int i = 0; i < range; ++i)
		{
			PLCContactorNumber temp = new PLCContactorNumber(beginNumber.getBCDCode(), beginNumber.getHEXCode());
			returnArray.add(temp);
			beginNumber.add(1);
		}

		return returnArray;
	}

	/**
	 * 解析寄存器读取指令
	 * @param locationNumber 站号
	 * @param beginAddress 起始地址
	 * @param endAddress 结束地址
	 */
	private ArrayList<PLCDataRegisterReadInstruction> parseDataRegisterReadInstruction
	(String locationNumber, String beginAddress, String endAddress)
	{
		PLCDataRegisterNumber registerNumber = new PLCDataRegisterNumber(beginAddress, endAddress);
		ArrayList<PLCDataRegisterReadInstruction> returnArray = new ArrayList<PLCDataRegisterReadInstruction>();

		PLCDataRegisterReadInstruction readRegisterIns = new PLCDataRegisterReadInstruction();
		int locLength = locationNumber.length();
		// 设置站号
		readRegisterIns.setLocationNumber_high(locationNumber.substring(0, locLength / 2));
		readRegisterIns.setLocationNumber_low(locationNumber.substring(locLength / 2, locLength));
		// 设置寄存器代码
		readRegisterIns.setDataCode(PLCDataCode.PLC_DATA_REGISTER_CODE);

		// 如果寄存器编号之间的差值超出最大限制
		if (registerNumber.range() > this.maxDataRegisterRange)
		{
			int range = registerNumber.range();
			int beginNumber = Integer.parseInt(beginAddress);
			// 计算需要分隔的次数
			int time = range / this.maxDataRegisterRange;
			// 计算余下的地址数
			int overFlowNumber = range % this.maxDataRegisterRange;
			for (int i = 0; i < time; ++i)
			{
				// 初始化指令
				PLCDataRegisterReadInstruction insPiece = new PLCDataRegisterReadInstruction();
				// 设置站号
				insPiece.setLocationNumber_high(readRegisterIns.getLocationNumber_high());
				insPiece.setLocationNumber_low(readRegisterIns.getLocationNumber_low());
				// 设置寄存器代码
				insPiece.setDataCode(PLCDataCode.PLC_DATA_REGISTER_CODE);
				// 设置寄存器编号
				insPiece.setDataRegisterNumber(new PLCDataRegisterNumber(
						String.valueOf(beginNumber),
						String.valueOf(beginNumber + this.maxDataRegisterRange - 1)));
				// 设置检错码
				insPiece.setBBC();
				// 递增地址
				beginNumber += this.maxDataRegisterRange;
				// 添加指令
//				this.readRegisterInstructionList.add(insPiece);
				returnArray.add(insPiece);
			}

			// 如果有多余的地址
			if (overFlowNumber > 0)
			{
				// 设置寄存器编号
				readRegisterIns.setDataRegisterNumber(new PLCDataRegisterNumber(
						String.valueOf(beginNumber),
						endAddress));
				// 设置检错码
				readRegisterIns.setBBC();
				// 添加指令
//				this.readRegisterInstructionList.add(readRegisterIns);
				returnArray.add(readRegisterIns);
			}
		}
		else
		{
			// 设置寄存器编号
			readRegisterIns.setDataRegisterNumber(registerNumber);
			// 设置检错码
			readRegisterIns.setBBC();
			// 添加指令
//			this.readRegisterInstructionList.add(readRegisterIns);
			returnArray.add(readRegisterIns);
		}

		return returnArray;
	}

	/**
	 * 解析多触点读取指令
	 * @param locationNumber 站号
	 * @param beginAddress 起始地址
	 * @param endAddress 结束地址
	 */
	private ArrayList<PLCMultipleContactorReadInstruction> parseContactorReadInstruction
	(String locationNumber, String beginAddress, String endAddress)
	{
		ArrayList<PLCMultipleContactorReadInstruction> returnArray = new ArrayList<PLCMultipleContactorReadInstruction>();

		// 初始化触点编号
		PLCContactorNumber beginNumber = new PLCContactorNumber(beginAddress.substring(0, beginAddress.length() - 1),
				beginAddress.charAt(beginAddress.length() - 1));
		PLCContactorNumber endNumber = new PLCContactorNumber(endAddress.substring(0, endAddress.length() - 1),
				endAddress.charAt(endAddress.length() - 1));
		// 获取地址两个编号的差值
		int range = PLCContactorNumber.rangeOf(beginNumber, endNumber);

		// 初始化指令
		PLCMultipleContactorReadInstruction readIns = new PLCMultipleContactorReadInstruction();
		// 设置站号
		int locLength = locationNumber.length();
		readIns.setLocationNumber_high(locationNumber.substring(0, locLength / 2));
		readIns.setLocationNumber_low(locationNumber.substring(locLength / 2, locLength));
		// 初始化触点代码和触点编码数组
		ArrayList<String> insCodes = new ArrayList<String>();
		ArrayList<PLCContactorNumber> insNumbers = new ArrayList<PLCContactorNumber>();

		// 如果两个编号相差大于触点最大范围
		if (range > maxContactorRange)
		{
			// 计算要进行的循环次数
			int time = range / maxContactorRange;
			// 取得未能被整除的编号数量
			int overFlowNumber = range % maxContactorRange;

			for (int i = 0; i < time; ++i)
			{
				// 初始化指令
				PLCMultipleContactorReadInstruction insPiece = new PLCMultipleContactorReadInstruction();
				// 设置站号
				insPiece.setLocationNumber_high(locationNumber.substring(0, locLength / 2));
				insPiece.setLocationNumber_low(locationNumber.substring(locLength / 2, locLength));
				insPiece.setCount(maxContactorRange);

				// 初始化触点代码和触点编码数组
				ArrayList<String> cCodes = new ArrayList<String>();
				ArrayList<PLCContactorNumber> cNumbers = new ArrayList<PLCContactorNumber>();

				for (int j = 0; j < maxContactorRange; ++j)
				{
					// 设置新的触点编号
					PLCContactorNumber newNumber = new PLCContactorNumber(beginNumber.getBCDCode(), beginNumber.getHEXCode());
					// 添加触点代码和触点编号
					cCodes.add(PLCContactorCode.PLC_INNER_RELAY_CODE);
					cNumbers.add(newNumber);
					// 递增起始触点编号
					if (!beginNumber.isMax())
					{
						beginNumber.add(1);
					}
				}

				// 添加指令到数组中
				insPiece.setContactorCodes(cCodes);
				insPiece.setContactorNumbers(cNumbers);
				insPiece.setBBC();
//				this.readContactorInstructionList.add(insPiece);/
				returnArray.add(insPiece);
			}

			// 如果有多余的地址
			if (overFlowNumber > 0)
			{
				for (int i = 0; i < overFlowNumber; ++i)
				{
					// 设置新的触点编号
					PLCContactorNumber newNumber = new PLCContactorNumber(beginNumber.getBCDCode(), beginNumber.getHEXCode());
					// 添加触点代码和触点编号
					insCodes.add(PLCContactorCode.PLC_INNER_RELAY_CODE);
					insNumbers.add(newNumber);
					if (!beginNumber.isMax())
					{
						beginNumber.add(1);
					}
				}

				// 添加最后一条指令到数组中
				readIns.setCount(overFlowNumber);
				readIns.setContactorCodes(insCodes);
				readIns.setContactorNumbers(insNumbers);
				readIns.setBBC();
//				this.readContactorInstructionList.add(readIns);
				returnArray.add(readIns);
			}

		}
		else
		{
			for (int i = 0; i < range; ++i)
			{
				// 设置新的触点编号
				PLCContactorNumber newNumber = new PLCContactorNumber(beginNumber.getBCDCode(), beginNumber.getHEXCode());
				// 添加触点代码和触点编号
				insCodes.add(PLCContactorCode.PLC_INNER_RELAY_CODE);
				insNumbers.add(newNumber);
				beginNumber.add(1);
			}

			// 添加指令到数组中
			readIns.setCount(range);
			readIns.setContactorCodes(insCodes);
			readIns.setContactorNumbers(insNumbers);
			readIns.setBBC();
//			this.readContactorInstructionList.add(readIns);
			returnArray.add(readIns);
		}

		return returnArray;
	}

	/**
	 * 解析寄存器写入指令
	 * @param locationNumber 站号
	 * @param beginAddress 起始地址
	 * @param endAddress 结束地址
	 */
	private ArrayList<PLCDataRegisterWriteInstruction> parseDataRegisterWriteInstruction
	(String locationNumber, String beginAddress, String endAddress, String data)
	{
		PLCDataRegisterNumber registerNumber = new PLCDataRegisterNumber(beginAddress, endAddress);
		ArrayList<PLCDataRegisterWriteInstruction> returnArray = new ArrayList<PLCDataRegisterWriteInstruction>();

		PLCDataRegisterWriteInstruction writeRegisterIns = new PLCDataRegisterWriteInstruction();
		int locLength = locationNumber.length();
		// 设置站号
		writeRegisterIns.setLocationNumber_high(locationNumber.substring(0, locLength / 2));
		writeRegisterIns.setLocationNumber_low(locationNumber.substring(locLength / 2, locLength));
		// 设置寄存器代码
		writeRegisterIns.setDataCode(PLCDataCode.PLC_DATA_REGISTER_CODE);

		// 写入数据
		ArrayList<String> datas = new ArrayList<>();
		for (int j = 0; j < maxDataRegisterRange; ++j)
		{
			datas.add(data);
		}

		// 如果寄存器编号之间的差值超出最大限制
		if (registerNumber.range() > this.maxDataRegisterRange)
		{
			int range = registerNumber.range();
			int beginNumber = Integer.parseInt(beginAddress);
			// 计算需要分隔的次数
			int time = range / this.maxDataRegisterRange;
			// 计算余下的地址数
			int overFlowNumber = range % this.maxDataRegisterRange;
			for (int i = 0; i < time; ++i)
			{
				// 初始化指令
				PLCDataRegisterWriteInstruction insPiece = new PLCDataRegisterWriteInstruction();
				// 设置站号
				insPiece.setLocationNumber_high(writeRegisterIns.getLocationNumber_high());
				insPiece.setLocationNumber_low(writeRegisterIns.getLocationNumber_low());
				// 设置寄存器代码
				insPiece.setDataCode(PLCDataCode.PLC_DATA_REGISTER_CODE);
				// 设置寄存器编号
				insPiece.setDataRegisterNumber(new PLCDataRegisterNumber(
						String.valueOf(beginNumber),
						String.valueOf(beginNumber + this.maxDataRegisterRange - 1)));
				// 设置数据
				insPiece.setWriteData(datas);
				// 设置检错码
				insPiece.setBBC();
				// 递增地址
				beginNumber += this.maxDataRegisterRange;
				// 添加数据
				// 添加指令
				returnArray.add(insPiece);
			}

			// 如果有多余的地址
			if (overFlowNumber > 0)
			{
				// 设置寄存器编号
				PLCDataRegisterNumber dNumber = new PLCDataRegisterNumber(
						String.valueOf(beginNumber),
						endAddress);
				writeRegisterIns.setDataRegisterNumber(dNumber);
				// 设置数据
				ArrayList<String> remainDatas = new ArrayList<>();

				for (int j = 0; j < dNumber.range(); ++j)
				{
					remainDatas.add(data);
				}
				writeRegisterIns.setWriteData(remainDatas);
				// 设置检错码
				writeRegisterIns.setBBC();
				// 添加指令
//				this.readRegisterInstructionList.add(readRegisterIns);
				returnArray.add(writeRegisterIns);
			}
		}
		else
		{
			// 设置寄存器编号
			writeRegisterIns.setDataRegisterNumber(registerNumber);
			// 设置数据
			ArrayList<String> remainDatas = new ArrayList<>();
			for (int j = 0; j < registerNumber.range(); ++j)
			{
				remainDatas.add(data);
			}
			writeRegisterIns.setWriteData(remainDatas);
			// 设置检错码
			writeRegisterIns.setBBC();
			// 添加指令
//			this.readRegisterInstructionList.add(readRegisterIns);
			returnArray.add(writeRegisterIns);
		}

//		for (PLCRequestInstruction ins : returnArray)
//		{
//			System.out.println(ins);
//		}

		return returnArray;
	}

	/**
	 * 解析多触点写入指令
	 * @param locationNumber 站号
	 * @param beginAddress 起始地址
	 * @param endAddress 结束地址
	 */
	private ArrayList<PLCMultipleContactorWriteInstruction> parseContactorWriteInstruction(String locationNumber, String beginAddress, String endAddress, String data)
	{
		ArrayList<PLCMultipleContactorWriteInstruction> returnArray = new ArrayList<PLCMultipleContactorWriteInstruction>();

		// 初始化触点编号
		PLCContactorNumber beginNumber = new PLCContactorNumber(beginAddress.substring(0, beginAddress.length() - 1),
				beginAddress.charAt(beginAddress.length() - 1));
		PLCContactorNumber endNumber = new PLCContactorNumber(endAddress.substring(0, endAddress.length() - 1),
				endAddress.charAt(endAddress.length() - 1));
		// 获取地址两个编号的差值
		int range = PLCContactorNumber.rangeOf(beginNumber, endNumber);

		// 初始化指令
		PLCMultipleContactorWriteInstruction readIns = new PLCMultipleContactorWriteInstruction();
		// 设置站号
		int locLength = locationNumber.length();
		readIns.setLocationNumber_high(locationNumber.substring(0, locLength / 2));
		readIns.setLocationNumber_low(locationNumber.substring(locLength / 2, locLength));
		// 初始化触点代码和触点编码数组
		ArrayList<String> insCodes = new ArrayList<String>();
		ArrayList<PLCContactorNumber> insNumbers = new ArrayList<PLCContactorNumber>();

		// 写入数据
		ArrayList<String> datas = new ArrayList<>();
		for (int i = 0; i < maxContactorRange; ++i)
		{
			datas.add(data);
		}

		// 如果两个编号相差大于触点最大范围
		if (range > maxContactorRange)
		{
			// 计算要进行的循环次数
			int time = range / maxContactorRange;
			// 取得未能被整除的编号数量
			int overFlowNumber = range % maxContactorRange;

			for (int i = 0; i < time; ++i)
			{
				// 初始化指令
				PLCMultipleContactorWriteInstruction insPiece = new PLCMultipleContactorWriteInstruction();
				// 设置站号
				insPiece.setLocationNumber_high(locationNumber.substring(0, locLength / 2));
				insPiece.setLocationNumber_low(locationNumber.substring(locLength / 2, locLength));
				insPiece.setCount(maxContactorRange);

				// 初始化触点代码和触点编码数组
				ArrayList<String> cCodes = new ArrayList<String>();
				ArrayList<PLCContactorNumber> cNumbers = new ArrayList<PLCContactorNumber>();

				for (int j = 0; j < maxContactorRange; ++j)
				{
					// 设置新的触点编号
					PLCContactorNumber newNumber = new PLCContactorNumber(beginNumber.getBCDCode(), beginNumber.getHEXCode());
					// 添加触点代码和触点编号
					cCodes.add(PLCContactorCode.PLC_INNER_RELAY_CODE);
					cNumbers.add(newNumber);
					// 递增起始触点编号
					if (!beginNumber.isMax())
					{
						beginNumber.add(1);
					}
				}

				// 添加指令到数组中
				insPiece.setContactorCodes(cCodes);
				insPiece.setContactorNumbers(cNumbers);
				// 设置数据
				insPiece.setWriteData(datas);
				insPiece.setBBC();
//				this.readContactorInstructionList.add(insPiece);/
				returnArray.add(insPiece);
			}

			// 如果有多余的地址
			if (overFlowNumber > 0)
			{
				ArrayList<String> remainDatas = new ArrayList<>();
				for (int i = 0; i < overFlowNumber; ++i)
				{
					// 设置新的触点编号
					PLCContactorNumber newNumber = new PLCContactorNumber(beginNumber.getBCDCode(), beginNumber.getHEXCode());
					// 添加触点代码和触点编号
					insCodes.add(PLCContactorCode.PLC_INNER_RELAY_CODE);
					insNumbers.add(newNumber);
					remainDatas.add(data);
					if (!beginNumber.isMax())
					{
						beginNumber.add(1);
					}
				}

				// 添加最后一条指令到数组中
				readIns.setCount(overFlowNumber);
				readIns.setContactorCodes(insCodes);
				readIns.setContactorNumbers(insNumbers);
				// 设置数据
				readIns.setWriteData(remainDatas);
				readIns.setBBC();
//				this.readContactorInstructionList.add(readIns);
				returnArray.add(readIns);
			}

		}
		else
		{
			ArrayList<String> remainDatas = new ArrayList<>();

			for (int i = 0; i < range; ++i)
			{
				// 设置新的触点编号
				PLCContactorNumber newNumber = new PLCContactorNumber(beginNumber.getBCDCode(), beginNumber.getHEXCode());
				// 添加触点代码和触点编号
				insCodes.add(PLCContactorCode.PLC_INNER_RELAY_CODE);
				insNumbers.add(newNumber);
				remainDatas.add(data);
				beginNumber.add(1);
			}

			// 添加指令到数组中
			readIns.setCount(range);
			readIns.setContactorCodes(insCodes);
			readIns.setContactorNumbers(insNumbers);
			// 设置数据
			readIns.setWriteData(remainDatas);
			readIns.setBBC();
//			this.readContactorInstructionList.add(readIns);
			returnArray.add(readIns);
		}

//		for (PLCRequestInstruction ins : returnArray)
//		{
//			System.out.println(ins);
//		}

		return returnArray;
	}
}
